﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.CodeAnalysis;
using System.Security.Permissions;
using System.Windows.Threading;

namespace System.Windows.ApplicationFramework
{
    /// <summary>
    /// Provides utility methods that perform common tasks involving a view.
    /// </summary>
    public static class ViewExtensions
    {
        /// <summary>
        /// Gets the ViewModel which is associated with the specified view.
        /// </summary>
        /// <typeparam name="T">The type of the ViewModel</typeparam>
        /// <param name="view">The view.</param>
        /// <returns>The associated ViewModel, or <c>null</c> when no ViewModel was found.</returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
        public static T GetViewModel<T>(this IView view) where T : ViewModel
        {
            object dataContext = view.DataContext;
            if (dataContext == null)
            {
                DoEvents();
                dataContext = view.DataContext;
            }
            return dataContext as T;
        }

        /// <summary>
        /// Execute the event queue of the dispatcher.
        /// </summary>
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        private static void DoEvents()
        {
            DispatcherFrame frame = new DispatcherFrame();
            Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
                new DispatcherOperationCallback(ExitFrame), frame);
            Dispatcher.PushFrame(frame);
        }

        private static object ExitFrame(object frame)
        {
            ((DispatcherFrame)frame).Continue = false;
            return null;
        }
    }
}
